package com.topisv.tms.service;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;
import org.springside.modules.persistence.SearchFilter.Operator;

import com.topisv.tms.entity.BackupTaskOrdeno;
import com.topisv.tms.entity.BatchTask;
import com.topisv.tms.entity.EdiOrder;
import com.topisv.tms.entity.EdiOrderItem;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.log.OrderLog;
import com.topisv.tms.entity.stock.CusStock;
import com.topisv.tms.repository.BackupTaskOrdenoDao;
import com.topisv.tms.repository.BatchTaskDao;
import com.topisv.tms.repository.CusStockMergeDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.EdiOrderDao;
import com.topisv.tms.repository.EdiOrderItemDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.log.OrderLogDao;
import com.topisv.tms.repository.stock.CusStockDao;
import com.topisv.tms.utils.BackupTaskRule;
import com.topisv.tms.utils.enums.StatusEnums;

//Spring Bean的标识.
@Component
// 默认将类中的所有public函数纳入事务管理.
@Transactional(readOnly = true)
public class BatchTaskService {

	@Autowired
	private BatchTaskDao batchTaskDao;
	@Autowired
	private BackupTaskOrdenoDao backupTaskOrdenoDao;
	@Autowired
	private EdiOrderDao ediOrderDao;
	@Autowired
	private EdiOrderItemDao ediOrderItemDao;

	@Autowired
	private CusStockDao cusStockDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private CusStockMergeDao cusStockMergeDao;
	@Autowired
	private OrderLogDao orderLogDao;

	private List<EdiOrder> getEdiOrder(String ordenos)
			throws Exception {
		List<EdiOrder> ediOrdersPages = new ArrayList<EdiOrder>();
		try {
			String[] ordenoLists = ordenos.split(":");
			for (String o : ordenoLists) {
				ediOrdersPages.add(ediOrderDao.findByOrdeno(o));
			}
		} catch (Exception e) {
			throw e;
		}
		return ediOrdersPages;
	}

	/**
	 * wms生成分拣批次
	 * 
	 * @param ordenos
	 * @param jobuuid
	 * @param orderType
	 * @param customerCode
	 * @param count
	 * @param areaGroupCode
	 * @param batchType
	 * @param ordenoSourceCode
	 * @return
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class, readOnly = false)
	public List<BatchTask> createBatchTask(String warehouseCode,String ordenos, String jobuuid,
			String orderType, String customerCode, int count,
			String areaGroupLists, String ordenoSourceCode)
			throws Exception {
		List<BatchTask> batchTasks = new ArrayList<BatchTask>();
		List<EdiOrder> ediOrdersPages=getEdiOrder(ordenos);
		int length = ediOrdersPages.size();
		int pageCount = length % count == 0 ? length / count : length / count
				+ 1;
		for (int i = 0; i < pageCount; i++) {
			int fromIndex = i * count;
			int toIndex = (i + 1) * count > length ? length : (i + 1) * count;
			List<EdiOrder> obj = ediOrdersPages.subList(fromIndex, toIndex);
			BatchTask batchTask = createBatchTask(warehouseCode,obj, jobuuid, orderType,
					customerCode, areaGroupLists, ordenoSourceCode);
			batchTasks.add(batchTask);
		}
		return batchTasks;
	}
	
	/**
	 * WMS生成分拣批次
	 * @param ediOrdersPages
	 * @param jobuuid
	 * @param orderType
	 * @param customerCode
	 * @param areaLists
	 * @param batchType
	 * @param ordenoSourceCode
	 * @return
	 * @throws Exception
	 */
	@Transactional(rollbackFor = Exception.class, readOnly = false)
	public BatchTask createBatchTask(String warehouseCode,List<EdiOrder> ediOrdersPages,
			String jobuuid, String orderType, String customerCode,
			String areaGroupLists,  String ordenoSourceCode)
			throws Exception {
		BatchTask batchTask = null;
		List<BackupTaskOrdeno> backupTaskOrdenos = null;
		int skuQty = 0;
		try {
			if (ediOrdersPages.isEmpty()) {
				return null;
			}
			User curUser=this.userDao.findByJobuuid(jobuuid);
			List<OrderLog> orderLogList=new ArrayList<OrderLog>();
			String areaGroup[] = areaGroupLists.split("--");
			DecimalFormat df=new DecimalFormat("0000000");
			batchTask = new BatchTask();
			batchTask.setBatchType(StatusEnums.ZWAREHOUSE.getStatus());
			batchTask.setCreateDate(new Date());
			batchTask.setJobuuid(jobuuid);
			batchTask.setUpdateDate(new Date());
			batchTask.setStatus("pending");
			batchTask.setWarehouseCode(warehouseCode);
			batchTask.setType(orderType);
			batchTask.setCustomerCode(customerCode);
			batchTask.setAreaGroupCode(areaGroup[0]);
			batchTask.setAreaGroupName(areaGroup[1]);
			batchTask.setBatchTaskCode("");
			batchTask.setShopSourceCode(ordenoSourceCode);
			this.batchTaskDao.save(batchTask);
			String batchTaskCode = "G"+customerCode+df.format(batchTask.getId());
			batchTask.setBatchTaskCode(batchTaskCode);
			backupTaskOrdenos = new ArrayList<BackupTaskOrdeno>();
			int orderNumber = 0;
			for (EdiOrder ediOrdersPage : ediOrdersPages) {
				if (ediOrdersPage.getOrderType() != null) {
					if (!orderType.equals(ediOrdersPage.getOrderType())) {
						continue;
					}
				}
				if ("finish".equals(ediOrdersPage.getStatus())) {
					throw new Exception(ediOrdersPage.getOrdeno()+ ":该订单号已经分配分拣批次");
				}
				ediOrdersPage.setMessage("JF");
				orderNumber++;
				int productQty = 0;
				String ordeno = ediOrdersPage.getOrdeno();
				BackupTaskOrdeno backupTaskOrdeno = new BackupTaskOrdeno();
				backupTaskOrdeno.setOrdeno(ordeno);
				backupTaskOrdeno.setBatchTaskCode(batchTaskCode);
				backupTaskOrdeno.setWaybillNo(ediOrdersPage.getWaybillNo());
				backupTaskOrdeno.setPickStatus("pending");
				backupTaskOrdenos.add(backupTaskOrdeno);
				ediOrdersPage.setStatus("finish");
				List<EdiOrderItem> ediOrderItems = ediOrderItemDao.findByOrdeno(ordeno);
				if (ediOrdersPage.getOrderType() == null) {
					if (ediOrderItems.isEmpty()) {
						throw new Exception("订单号:" + ordeno + "商品明细不存在");
					}
					if (ediOrderItems.size() > 1) {
						ediOrdersPage.setOrderType("multiple");
					} else if (ediOrderItems.get(0).getQty() > 1) {
						ediOrdersPage.setOrderType("multiple");
					} else {
						ediOrdersPage.setOrderType("single");
					}
				}
				// 设置数量
				if (ediOrdersPage.getSkuQty() == 0) {
					for (EdiOrderItem ei : ediOrderItems) {
						productQty += ei.getQty();
					}
					ediOrdersPage.setSkuQty(productQty);
				}
				skuQty = ediOrdersPage.getSkuQty();
				ediOrdersPage.setBatchTaskCode(batchTaskCode);
				ediOrderDao.save(ediOrdersPage);
				
				//订单日志
				OrderLog orderlog=new OrderLog(ediOrdersPage.getOrdeno(),
						customerCode, 
						"1", //操作类型 （1.创建批次 2.创建任务  3.拣货完成 4.包装完成 5.发货完成 6.签收完成 7.异常登记 8.完成灯光拣选任务 9.打印单据）
						curUser,
						new Date(),
						null, 
						curUser.getRealname()+"创建作业批次");
				orderLogList.add(orderlog);
			}
			
			batchTask.setOrdenoQty(orderNumber);
			batchTask.setSkuQty(skuQty);
			backupTaskOrdenoDao.save(backupTaskOrdenos);
			batchTaskDao.save(batchTask);
			this.orderLogDao.save(orderLogList);
		} catch (Exception e) {
			throw e;
		}
		return batchTask;
	}

	public List<BatchTask> findByStatusAndCustomerCode(String status,
			String customerCode) {
		return batchTaskDao.findByStatusAndCustomerCode(status, customerCode);
	}

	public List<BatchTask> findBatchTaskStatus(final String customers,
			final String areagroups, final String status) {
		Specification<BatchTask> spec = null;
		List<BatchTask> batchTasks = null;
		try {
			spec = buildSpecification(customers, areagroups, status);
			batchTasks = batchTaskDao.findAll(spec);
		} catch (Exception e) {
			
		}
		return batchTasks;
	}

	private Specification<BatchTask> buildSpecification(final String customers,
			final String areagroups, final String status) {
		return new Specification<BatchTask>() {
			@Override
			public Predicate toPredicate(Root<BatchTask> r, CriteriaQuery<?> q,
					CriteriaBuilder cb) {

				Predicate pre = cb.conjunction();
				if (StringUtils.isNotBlank(customers)) {
					String[] customerLists = customers.split(":");
					ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerLists.length];
					int i = 0;
					for (String customer : customerLists) {
						tempCustomerCode[i] = (ComparisonPredicate) cb.equal(
								r.get("customerCode"), customer);
						i++;
					}
					pre.getExpressions().add(cb.or(tempCustomerCode));
				}

				if (StringUtils.isNotBlank(areagroups)) {
					String[] areagroupLists = areagroups.split(":");
					ComparisonPredicate[] tempAreagroups = new ComparisonPredicate[areagroupLists.length];
					int i = 0;
					for (String areagroup : areagroupLists) {
						tempAreagroups[i] = (ComparisonPredicate) cb.equal(
								r.get("areaGroupCode"), areagroup);
						i++;
					}
					pre.getExpressions().add(cb.or(tempAreagroups));
				}

				if (StringUtils.isNotBlank(status)) {
					pre.getExpressions().add(cb.equal(r.get("status"), status));
				}

				return pre;
			}

		};
	}

	

	@Transactional(readOnly = false)
	public void countOrdenos(List<EdiOrder> ediOrders) throws Exception {
		if (ediOrders == null) {
			throw new Exception("参数不能为空");
		}
		try {
			for (EdiOrder e : ediOrders) {

				e.setIsdelv(true);// 总仓
				ediOrderDao.save(e);
			}
		} catch (Exception e) {
			throw e;
		}
	}

	
	

	

	public List<BatchTask> findByStatusAndJobuuid(String status, String jobuuid) {
		return batchTaskDao.findByStatusAndJobuuid(status, jobuuid);
	}

	/**
	 * 分页显示表内所有行.
	 */
	public Page<BatchTask> getPageBatchTasks(Map<String, Object> filterParams,
			int pageNumber, int pageSize, String sortType) {
		PageRequest pageRequest = buildPageRequest(pageNumber, pageSize,
				sortType);
		Specification<BatchTask> spec = buildSpecification(filterParams);
		return batchTaskDao.findAll(spec, pageRequest);
	}

	/**
	 * 分页显示表内所有行.
	 */
	public Page<BatchTask> getPageBatchTasks(Map<String, Object> filterParams,
			int pageNumber, int pageSize, String sortType, Date fromDate,
			Date endDate) {
		PageRequest pageRequest = buildPageRequest(pageNumber, pageSize,
				sortType);
		Specification<BatchTask> spec = buildSpecification(filterParams,
				fromDate, endDate);
		return batchTaskDao.findAll(spec, pageRequest);
	}

	/**
	 * 创建分页请求.
	 */
	private PageRequest buildPageRequest(int pageNumber, int pageSize,
			String sortType) {
		Sort sort = null;
		if (null != sortType) {
			if (sortType.endsWith("desc")) {
				sort = new Sort(Direction.DESC, "id");
			} else if (sortType.endsWith("asc")) {
				sort = new Sort(Direction.ASC, "id");
			}
		}
		return new PageRequest(pageNumber - 1, pageSize, sort);
	}

	private Specification<BatchTask> buildSpecification(
			Map<String, Object> filterParams, Date fromDate, Date endDate) {
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		filters.put("fromDate", new SearchFilter("createDate", Operator.GTE,
				fromDate));
		filters.put("toDate", new SearchFilter("createDate", Operator.LT,
				endDate));
		Specification<BatchTask> spec = DynamicSpecifications.bySearchFilter(
				filters.values(), BatchTask.class);
		return spec;
	}

	/**
	 * 创建动态查询条件组合.
	 */
	private Specification<BatchTask> buildSpecification(
			Map<String, Object> filterParams) {
		Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
		Specification<BatchTask> spec = DynamicSpecifications.bySearchFilter(
				filters.values(), BatchTask.class);
		return spec;
	}

	public List<BatchTask> findByStatus(String status) {
		return batchTaskDao.findByStatus(status);
	}

	public List<BatchTask> findByCreateDateBetween(Date startDate, Date endDate) {
		return batchTaskDao.findByCreateDateBetween(startDate, endDate);
	}

	public BatchTask findByBatchTaskCode(String batchTaskCode) {
		return batchTaskDao.findByBatchTaskCode(batchTaskCode);
	}

	@Transactional(readOnly = false)
	public List<BatchTask> save(List<BatchTask> arg0) {
		return (List<BatchTask>) batchTaskDao.save(arg0);
	}

	@Transactional(readOnly = false)
	public BatchTask save(BatchTask arg0) {
		return batchTaskDao.save(arg0);
	}

	@Transactional(rollbackFor = Exception.class, readOnly = false)
	public List<BatchTask> createBatchTask(List<EdiOrder> ediOrdersPages,
			String jobuuid, String orderType, String customerCode, int count,
			String areaLists, String batchType, String ordenoSourceCode)
			throws Exception {
		List<BatchTask> batchTasks = new ArrayList<BatchTask>();
		int length = ediOrdersPages.size();
		int pageCount = length % count == 0 ? length / count : length / count
				+ 1;
		for (int i = 0; i < pageCount; i++) {
			int fromIndex = i * count;
			int toIndex = (i + 1) * count > length ? length : (i + 1) * count;
			List<EdiOrder> obj = ediOrdersPages.subList(fromIndex, toIndex);
			BatchTask batchTask = createBatchTask(obj, jobuuid, orderType,
					customerCode, areaLists, batchType, ordenoSourceCode);
			batchTasks.add(batchTask);
		}
		return batchTasks;
	}

	@Transactional(rollbackFor = Exception.class, readOnly = false)
	public BatchTask createBatchTask(List<EdiOrder> ediOrdersPages,
			String jobuuid, String orderType, String customerCode, String date,
			String areaLists, String shopCode, String batchType)
			throws Exception {
		BatchTask batchTask = null;
		List<BackupTaskOrdeno> backupTaskOrdenos = null;
		int skuQty = 0;
		try {
			if (ediOrdersPages.isEmpty()) {
				return null;
			}
			String batchTaskCode = BackupTaskRule
					.getBatchTaskCode(customerCode);
			String areaGroup[] = areaLists.split("--");
			batchTask = new BatchTask();
			batchTask.setCreateDate(new Date());
			batchTask.setJobuuid(jobuuid);
			batchTask.setUpdateDate(new Date());
			batchTask.setStatus("pending");
			batchTask.setType(orderType);
			batchTask.setOrdenoQty(ediOrdersPages.size());
			batchTask.setDate(date);
			batchTask.setCustomerCode(customerCode);
			batchTask.setShopSourceCode(shopCode);
			batchTask.setAreaGroupCode(areaGroup[1]);
			batchTask.setAreaGroupName(areaGroup[2]);
			batchTask.setBatchTaskCode(batchTaskCode);
			backupTaskOrdenos = new ArrayList<BackupTaskOrdeno>();
			for (EdiOrder ediOrdersPage : ediOrdersPages) {
				int productQty = 0;
				String ordeno = ediOrdersPage.getOrdeno();
				BackupTaskOrdeno backupTaskOrdeno = new BackupTaskOrdeno();
				backupTaskOrdeno.setOrdeno(ordeno);
				backupTaskOrdeno.setWaybillNo(ediOrdersPage.getWaybillNo());// 设置运单号
				backupTaskOrdeno.setBatchTaskCode(batchTaskCode);
				backupTaskOrdenos.add(backupTaskOrdeno);
				skuQty = ediOrdersPage.getSkuQty();
				ediOrdersPage.setStatus("finish");
				List<EdiOrderItem> ediOrderItems = ediOrderItemDao
						.findByOrdeno(ordeno);
				if (ediOrdersPage.getOrderType() == null) {
					if (ediOrderItems.isEmpty()) {
						throw new Exception("订单号:" + ordeno + "商品明细不存在");
					}
					if (ediOrderItems.size() > 1) {
						ediOrdersPage.setOrderType("multiple");
					} else if (ediOrderItems.get(0).getQty() > 1) {
						ediOrdersPage.setOrderType("multiple");
					} else {
						ediOrdersPage.setOrderType("single");
					}
				}
				// 设置数量
				if (ediOrdersPage.getSkuQty() == 0) {
					for (EdiOrderItem ei : ediOrderItems) {
						productQty += ei.getQty();
					}
					ediOrdersPage.setSkuQty(productQty);
				}
				ediOrderDao.save(ediOrdersPage);
			}
			batchTask.setSkuQty(skuQty);
			backupTaskOrdenoDao.save(backupTaskOrdenos);
			batchTaskDao.save(batchTask);
		} catch (Exception e) {
			throw e;
		}
		return batchTask;
	}

	@Transactional(rollbackFor = Exception.class, readOnly = false)
	public BatchTask createBatchTask(List<EdiOrder> ediOrdersPages,
			String jobuuid, String orderType, String customerCode,
			String areaLists, String batchType, String ordenoSourceCode)
			throws Exception {
		BatchTask batchTask = null;
		List<BackupTaskOrdeno> backupTaskOrdenos = null;
		int skuQty = 0;
		try {
			if (ediOrdersPages.isEmpty()) {
				return null;
			}
			String batchTaskCode = BackupTaskRule
					.getBatchTaskCode(customerCode);
			String areaGroup[] = areaLists.split("--");

			batchTask = new BatchTask();
			batchTask.setBatchType(batchType);
			batchTask.setCreateDate(new Date());
			batchTask.setJobuuid(jobuuid);
			batchTask.setUpdateDate(new Date());
			batchTask.setStatus("pending");
			batchTask.setType(orderType);
			batchTask.setCustomerCode(customerCode);
			batchTask.setAreaGroupCode(areaGroup[1]);
			batchTask.setAreaGroupName(areaGroup[2]);
			batchTask.setBatchTaskCode(batchTaskCode);
			batchTask.setShopSourceCode(ordenoSourceCode);
			backupTaskOrdenos = new ArrayList<BackupTaskOrdeno>();
			int orderNumber = 0;
			for (EdiOrder ediOrdersPage : ediOrdersPages) {
				if (ediOrdersPage.getOrderType() != null) {
					if (!orderType.equals(ediOrdersPage.getOrderType())) {
						continue;
					}
				}
				if ("finish".equals(ediOrdersPage.getStatus())) {
					throw new Exception(ediOrdersPage.getOrdeno()
							+ ":该订单号已经分配分拣批次");
				}
				orderNumber++;
				int productQty = 0;
				String ordeno = ediOrdersPage.getOrdeno();
				BackupTaskOrdeno backupTaskOrdeno = new BackupTaskOrdeno();
				backupTaskOrdeno.setOrdeno(ordeno);
				backupTaskOrdeno.setBatchTaskCode(batchTaskCode);
				backupTaskOrdeno.setWaybillNo(ediOrdersPage.getWaybillNo());
				backupTaskOrdeno.setPickStatus("pending");
				backupTaskOrdenos.add(backupTaskOrdeno);
				ediOrdersPage.setStatus("finish");
				List<EdiOrderItem> ediOrderItems = ediOrderItemDao
						.findByOrdeno(ordeno);
				if (ediOrdersPage.getOrderType() == null) {
					if (ediOrderItems.isEmpty()) {
						throw new Exception("订单号:" + ordeno + "商品明细不存在");
					}
					if (ediOrderItems.size() > 1) {
						ediOrdersPage.setOrderType("multiple");
					} else if (ediOrderItems.get(0).getQty() > 1) {
						ediOrdersPage.setOrderType("multiple");
					} else {
						ediOrdersPage.setOrderType("single");
					}
				}
				// 设置数量
				if (ediOrdersPage.getSkuQty() == 0) {
					for (EdiOrderItem ei : ediOrderItems) {
						productQty += ei.getQty();
					}
					ediOrdersPage.setSkuQty(productQty);
				}
				skuQty = ediOrdersPage.getSkuQty();
				ediOrdersPage.setBatchTaskCode(batchTaskCode);
				ediOrderDao.save(ediOrdersPage);
			}
			batchTask.setOrdenoQty(orderNumber);

			batchTask.setSkuQty(skuQty);
			backupTaskOrdenoDao.save(backupTaskOrdenos);
			batchTaskDao.save(batchTask);
		} catch (Exception e) {
			throw e;
		}
		return batchTask;
	}

	/**
	 * 查找批次
	 * @param searchParams 查询参数
	 * @return
	 */
	public Page<BatchTask> loadBatch(int pageNumber, int pageSize, String sortType,Map<String, Object> searchParams) {
		Specification<BatchTask> spec = getWhereClause(searchParams);
		PageRequest pageRequest = buildPageRequest(pageNumber, pageSize,sortType);
		Page<BatchTask> batchList = this.batchTaskDao.findAll(spec, pageRequest);
		for(BatchTask b:batchList){
			User user=userDao.findByJobuuid(b.getJobuuid());
			if(user!=null){
				b.setUsername(user.getRealname());
			}
		}
		return batchList;
	}
	
	public List<BatchTask> loadBatch(Map<String, Object> searchParams) {
		Specification<BatchTask> spec = getWhereClause(searchParams);
		List<BatchTask> batchList = this.batchTaskDao.findAll(spec);
		for(BatchTask b:batchList){
			User user=userDao.findByJobuuid(b.getJobuuid());
			if(user!=null){
				b.setUsername(user.getRealname());
			}
		}
		return batchList;
	}
	
	/**
	 * 查询条件封装
	 * @param searchParams
	 * @return
	 */
	private Specification<BatchTask> getWhereClause(final Map<String, Object> searchParams) {
		
		return new Specification<BatchTask>(){
			
		    @Override
		    public Predicate toPredicate(Root<BatchTask> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
		      Predicate pre = cb.conjunction();
		      
		      String customerCode=(String) searchParams.get("customerCode");
		      if (StringUtils.isNotBlank(customerCode)) {
					String[] customerCodes = customerCode.split(":");
					ComparisonPredicate[] tempCustomerCode = new ComparisonPredicate[customerCodes.length];
					int i = 0;
					for (String code : customerCodes) {
						tempCustomerCode[i] = (ComparisonPredicate) cb.equal(r.get("customerCode"), code);
						i++;
					}
					pre.getExpressions().add(cb.or(tempCustomerCode));
				}

		      Date fromDate= (Date) searchParams.get("fromDate");
		      if (fromDate != null) {
		        pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("createDate"), fromDate));
		      }
		      
		      Date toDate= (Date) searchParams.get("toDate");
		      if (toDate != null) {
		        pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("createDate"), toDate));
		      }
		      
		      String status=(String) searchParams.get("status");
		      if(StringUtils.isNotEmpty(status)){
					pre.getExpressions().add(cb.equal(r.get("status"),status));
			  }	
		      
		      String batchType=(String) searchParams.get("batchType");
		      if(StringUtils.isNotEmpty(batchType)){
					pre.getExpressions().add(cb.equal(r.get("type"),batchType));
			  }	
		      
		      String warehouseCode=(String) searchParams.get("warehouseCode");
		      if(StringUtils.isNotEmpty(warehouseCode)){
		    	  pre.getExpressions().add(cb.equal(r.get("warehouseCode"),warehouseCode));
		      }
		      
		      String areaGroupCode=(String) searchParams.get("areaGroupCode");
		      if(StringUtils.isNotEmpty(warehouseCode)){
		    	  pre.getExpressions().add(cb.equal(r.get("areaGroupCode"),areaGroupCode));
		      }
		      
		      return pre;
		    }
		  };
    }

	/**
	 * 查询批次
	 * @param batchCode 批次编码
	 * @return
	 */
	public BatchTask loadBatchByCode(String batchCode) {
		return this.batchTaskDao.findByBatchTaskCode(batchCode);
	}

	
	
	/**
	 * 创建任务_单件
	 * @param orderList 待处理订单
	 * @param workBatch 任务批次
	 * @param tactics 任务策略 SKU(SKU集中策略) path(路径优化策略) singleSKU(单品合拣策略) wholeBox(整箱分拣策略)
	 * @param taskcount 任务容量
	 * @return
	 * @throws Exception
	 */
	public List<BatchTask> createTask_single(List<BackupTaskOrdeno> orderList, BatchTask batch, String tactics, Integer taskcount) throws Exception {
		
		try {

			List<BatchTask> taskList = new ArrayList<BatchTask>();
			List<BackupTaskOrdeno> tempOrderList = new ArrayList<BackupTaskOrdeno>();

			//加载订单明细
			for (int i = 0; i < orderList.size(); i++) {
				BackupTaskOrdeno o = orderList.get(i);
				List<EdiOrderItem> orderItems = this.ediOrderItemDao.findByOrdeno(o.getOrdeno());
				o.setOrderItems(orderItems);
			}

			// ==================== SKU(SKU集中策略) ====================
//			if (tactics.equals("SKU")) {
			if (true) {

				//sku排序—按sku需求量
				Map<String, Integer> skuMap = new HashMap<String, Integer>();
				for (BackupTaskOrdeno o : orderList) {
					String sku = o.getOrderItems().get(0).getSku();
					if (skuMap.containsKey(sku)) {
						skuMap.put(sku, skuMap.get(sku) + 1);
					} else {
						skuMap.put(sku, 1);
					}
				}
				List<Map.Entry<String, Integer>> mappingList = new ArrayList<Map.Entry<String, Integer>>(skuMap.entrySet());
				Collections.sort(mappingList,
						new Comparator<Map.Entry<String, Integer>>() {
							public int compare(
									Map.Entry<String, Integer> mapping1,
									Map.Entry<String, Integer> mapping2) {
								return -mapping1.getValue().compareTo(mapping2.getValue());
							}
				});
				for (Map.Entry<String, Integer> mapping : mappingList) {
					String sku = mapping.getKey();
					for (BackupTaskOrdeno order : orderList) {
						if (order.getOrderItems().get(0).getSku().equals(sku)) {
							tempOrderList.add(order);
						}
					}
				}
				
				// 设置拣货库位、箱位
				this.setBoxCode_single(tempOrderList, batch.getCustomerCode(),null);
				
				// 分隔订单-按任务容量
				BatchTask task = null;
				for (int i = 0; i < tempOrderList.size(); i++) {
					BackupTaskOrdeno order = tempOrderList.get(i);
					if (i % taskcount == 0) {
						task = new BatchTask();
						task.setBatchTaskCode(batch.getBatchTaskCode());
						task.setCustomerCode(batch.getCustomerCode());
						task.setType("single");
						task.setOrderList(new ArrayList<BackupTaskOrdeno>());
						taskList.add(task);
					}
					task.getOrderList().add(order);
				}
				
				
				//set rankno
				for (BatchTask _task : taskList) {
					List<BackupTaskOrdeno> _orderList=_task.getOrderList();
					
					Collections.sort(_orderList,
						new Comparator<BackupTaskOrdeno>() {
							public int compare(
									BackupTaskOrdeno order1,
									BackupTaskOrdeno order2) {
								String stockInfo_1=order1.getStockInfo()==null?"":order1.getStockInfo();
								String stockInfo_2=order2.getStockInfo()==null?"":order2.getStockInfo();
								return stockInfo_1.compareTo(stockInfo_2);
							}
					});
					int rankno=0;
					for (BackupTaskOrdeno workOrder : _orderList) {
						workOrder.setRankno(++rankno);
					}
				}
				

			}
			return taskList;

		} catch (Exception e) {
			
			throw new Exception("===预览作业任务异常，批次号：" + batch.getBatchTaskCode());
		}

	}
	
	/**
	 * 创建任务_单件
	 * @param orderList 待处理订单
	 * @param workBatch 任务批次
	 * @param tactics 任务策略 SKU(SKU集中策略) path(路径优化策略) singleSKU(单品合拣策略) wholeBox(整箱分拣策略)
	 * @param taskcount 任务容量
	 * @return
	 * @throws Exception
	 */
	public List<BatchTask> createTask_single_1(List<BackupTaskOrdeno> orderList, BatchTask batch, String tactics, Integer taskcount) throws Exception {
		
		try {

			List<BatchTask> taskList = new ArrayList<BatchTask>();
			List<BackupTaskOrdeno> tempOrderList = new ArrayList<BackupTaskOrdeno>();

			//加载订单明细
			for (int i = 0; i < orderList.size(); i++) {
				BackupTaskOrdeno o = orderList.get(i);
				List<EdiOrderItem> orderItems = this.ediOrderItemDao.findByOrdeno(o.getOrdeno());
				o.setOrderItems(orderItems);
			}

			// ==================== SKU(SKU集中策略) ====================
//			if (tactics.equals("SKU")) {
			if (true) {

				//sku排序—按sku需求量
				Map<String, Integer> skuMap = new HashMap<String, Integer>();
				for (BackupTaskOrdeno o : orderList) {
					String sku = o.getOrderItems().get(0).getSku();
					if (skuMap.containsKey(sku)) {
						skuMap.put(sku, skuMap.get(sku) + 1);
					} else {
						skuMap.put(sku, 1);
					}
				}
				List<Map.Entry<String, Integer>> mappingList = new ArrayList<Map.Entry<String, Integer>>(skuMap.entrySet());
				Collections.sort(mappingList,
						new Comparator<Map.Entry<String, Integer>>() {
							public int compare(
									Map.Entry<String, Integer> mapping1,
									Map.Entry<String, Integer> mapping2) {
								return -mapping1.getValue().compareTo(mapping2.getValue());
							}
				});
				for (Map.Entry<String, Integer> mapping : mappingList) {
					String sku = mapping.getKey();
					for (BackupTaskOrdeno order : orderList) {
						if (order.getOrderItems().get(0).getSku().equals(sku)) {
							tempOrderList.add(order);
						}
					}
				}
				
				// 分隔订单-按任务容量
				BatchTask task = null;
				for (int i = 0; i < tempOrderList.size(); i++) {
					BackupTaskOrdeno order = tempOrderList.get(i);
					if (i % taskcount == 0) {
						task = new BatchTask();
						task.setBatchTaskCode(batch.getBatchTaskCode());
						task.setCustomerCode(batch.getCustomerCode());
						task.setType("single");
						task.setOrderList(new ArrayList<BackupTaskOrdeno>());
						taskList.add(task);
					}
					task.getOrderList().add(order);
				}
				
				
				//set rankno
				for (BatchTask _task : taskList) {
					List<BackupTaskOrdeno> _orderList=_task.getOrderList();
					
					Collections.sort(_orderList,
						new Comparator<BackupTaskOrdeno>() {
							public int compare(
									BackupTaskOrdeno order1,
									BackupTaskOrdeno order2) {
								String stockInfo_1=order1.getStockInfo()==null?"":order1.getStockInfo();
								String stockInfo_2=order2.getStockInfo()==null?"":order2.getStockInfo();
								return stockInfo_1.compareTo(stockInfo_2);
							}
					});
					int rankno=0;
					for (BackupTaskOrdeno workOrder : _orderList) {
						workOrder.setRankno(++rankno);
					}
				}
				
			}
			return taskList;

		} catch (Exception e) {
			
			throw new Exception("===预览作业任务异常，批次号：" + batch.getBatchTaskCode());
		}

	}
	
	/**
	 * 设置库位、箱位_单件
	 * @param workOrderList  作业订单集合
	 * @param customerCode 商户编码
	 * @param warehouseCode 仓库编码
	 * @return errorList 库存不足的sku序列（多个以逗号间隔）
	 * @throws Exception 
	 */
	private String setBoxCode_single(List<BackupTaskOrdeno> workOrderList, String customerCode,String warehouseCode) throws Exception {

		String errorList="";
		
		// sku数量分类
		Map<String, Integer> skuMap = new HashMap<String, Integer>();
		for (BackupTaskOrdeno o : workOrderList) {
			String sku = o.getOrderItems().get(0).getSku();
			if (skuMap.containsKey(sku)) {
				skuMap.put(sku, skuMap.get(sku) + 1);
			} else {
				skuMap.put(sku, 1);
			}
		}

		// 给每个sku分配库存
		for (String sku : skuMap.keySet()) {
			
			int sku_num = skuMap.get(sku); // 每个sku需求数量.
			List<CusStock> stockList = this.cusStockDao.loadStock(customerCode, sku);

			// 库位排序：商品数量升序排列，
			Collections.sort(stockList, new Comparator<CusStock>() {
				public int compare(CusStock o1, CusStock o2) {
					return o1.getSalesNum().compareTo(o2.getSalesNum());
				}
			});
			
			boolean flag = false;
			// 找到最接近满足的箱位
			for (CusStock cusStock : stockList) {
				if (cusStock.getSalesNum() >= sku_num) {
					for (BackupTaskOrdeno pOrder : workOrderList) {
						String _sku = pOrder.getOrderItems().get(0).getSku();
						String _stockInfo = pOrder.getStockInfo();
						if (_sku.equals(sku) && StringUtils.isEmpty(_stockInfo)) {
							pOrder.setStockInfo(cusStock.getStockCode() + "_"+ cusStock.getBoxCode() + "_" + _sku + "_"+ 1 + ";");
						}
					}
					sku_num = 0;
					cusStock.setSalesNum(cusStock.getSalesNum()-sku_num);
					flag = true;
					break;
				}
			}

			// 如果没有找到最接近的箱位，箱位组合分配。
			if (!flag) {
				Collections.reverse(stockList); // 排序，商品数量降序
				for (CusStock cusStock : stockList) {
                    
					if (sku_num == 0){
						break;
					}
					
					for (BackupTaskOrdeno pOrder : workOrderList) {
						String _sku = pOrder.getOrderItems().get(0).getSku();
						String _stockInfo = pOrder.getStockInfo();
						if (_sku.equals(sku) && StringUtils.isBlank(_stockInfo)) {
							pOrder.setStockInfo(cusStock.getStockCode() + "_" + cusStock.getBoxCode() + "_" + _sku + "_" + 1 + ";");
							sku_num--;
							cusStock.setSalesNum(cusStock.getSalesNum()-1);
							
							if(cusStock.getSalesNum()==0){
								break;
							}
							
						}
					}
					
				}
				
			}
			
			if(sku_num>0){
				if(errorList.length()>0){
					errorList+=",";
				}
				errorList+=sku;
			}
		}
		
		return errorList;
	}
	
	

	/**
	 * 创建任务_多件
	 * @param orderList 待处理订单
	 * @param workBatch 任务批次
	 * @param tactics 任务策略 SKU(SKU集中策略) path(路径优化策略) singleSKU(单品合拣策略) wholeBox(整箱分拣策略)
	 * @param taskcount 任务容量
	 * @return
	 * @throws Exception
	 */
	public List<BatchTask> createTask_multi(List<BackupTaskOrdeno> orderList,BatchTask batchTask, String tactics, Integer taskcount) throws Exception {
		try {

			List<BatchTask> taskList = new ArrayList<BatchTask>();
			List<BackupTaskOrdeno> tempOrderList = new ArrayList<BackupTaskOrdeno>();
			tempOrderList=orderList;

			for (int i = 0; i < orderList.size(); i++) {
				BackupTaskOrdeno o = orderList.get(i);
				List<EdiOrderItem> orderItems = this.ediOrderItemDao.findByOrdeno(o.getOrdeno());
				o.setOrderItems(orderItems);
			}

			// 设置拣货库位、箱位
//			this.setBoxCode_multi(tempOrderList, batchTask.getCustomerCode(),batchTask.getWarehouseCode());
			this.setBoxCode_multi(tempOrderList, batchTask.getCustomerCode(),null);
			
			// 分隔订单-按任务容量
			BatchTask task = null;
			for (int i = 0; i < tempOrderList.size(); i++) {
				BackupTaskOrdeno order = tempOrderList.get(i);
				if (i % taskcount == 0) {
					task = new BatchTask();
					task.setBatchTaskCode(batchTask.getBatchTaskCode());
					task.setCustomerCode(batchTask.getCustomerCode());
					task.setType("multi"); //任务类型 (single: 单件 multi: 多件)
					task.setOrderList(new ArrayList<BackupTaskOrdeno>());
					taskList.add(task);
				}
				task.getOrderList().add(order);
			}
			
			//set rankno
			for (BatchTask _task : taskList) {
				List<BackupTaskOrdeno> _orderList=_task.getOrderList();
				
				Collections.sort(_orderList,
					new Comparator<BackupTaskOrdeno>() {
						public int compare(
								BackupTaskOrdeno order1,
								BackupTaskOrdeno order2) {
							String stockInfo_1=order1.getStockInfo()==null?"":order1.getStockInfo();
							String stockInfo_2=order2.getStockInfo()==null?"":order2.getStockInfo();
							return stockInfo_1.compareTo(stockInfo_2);
						}
				});
				
				int rankno=0;
				for (BackupTaskOrdeno workOrder : _orderList) {
					workOrder.setRankno(++rankno);
				}
			}
			
			return taskList;

		} catch (Exception e) {
			
			throw new Exception("===预览作业任务异常，批次号：" + batchTask.getBatchTaskCode());
		}

	}
	
	/**
	 * 创建任务_多件
	 * @param orderList 待处理订单
	 * @param workBatch 任务批次
	 * @param tactics 任务策略 SKU(SKU集中策略) path(路径优化策略) singleSKU(单品合拣策略) wholeBox(整箱分拣策略)
	 * @param taskcount 任务容量
	 * @return
	 * @throws Exception
	 */
	public List<BatchTask> createTask_multi_1(List<BackupTaskOrdeno> orderList,BatchTask batchTask, String tactics, Integer taskcount) throws Exception {
		try {

			List<BatchTask> taskList = new ArrayList<BatchTask>();
			List<BackupTaskOrdeno> tempOrderList = new ArrayList<BackupTaskOrdeno>();
			tempOrderList=orderList;

			for (int i = 0; i < orderList.size(); i++) {
				BackupTaskOrdeno o = orderList.get(i);
				List<EdiOrderItem> orderItems = this.ediOrderItemDao.findByOrdeno(o.getOrdeno());
				o.setOrderItems(orderItems);
			}

			// 分隔订单-按任务容量
			BatchTask task = null;
			for (int i = 0; i < tempOrderList.size(); i++) {
				BackupTaskOrdeno order = tempOrderList.get(i);
				if (i % taskcount == 0) {
					task = new BatchTask();
					task.setBatchTaskCode(batchTask.getBatchTaskCode());
					task.setCustomerCode(batchTask.getCustomerCode());
					task.setType("multi"); //任务类型 (single: 单件 multi: 多件)
					task.setOrderList(new ArrayList<BackupTaskOrdeno>());
					taskList.add(task);
				}
				task.getOrderList().add(order);
			}
			
			//set rankno
			for (BatchTask _task : taskList) {
				List<BackupTaskOrdeno> _orderList=_task.getOrderList();
				
				Collections.sort(_orderList,
					new Comparator<BackupTaskOrdeno>() {
						public int compare(
								BackupTaskOrdeno order1,
								BackupTaskOrdeno order2) {
							String stockInfo_1=order1.getStockInfo()==null?"":order1.getStockInfo();
							String stockInfo_2=order2.getStockInfo()==null?"":order2.getStockInfo();
							return stockInfo_1.compareTo(stockInfo_2);
						}
				});
				
				int rankno=0;
				for (BackupTaskOrdeno workOrder : _orderList) {
					workOrder.setRankno(++rankno);
				}
			}
			
			return taskList;

		} catch (Exception e) {
			
			throw new Exception("===预览作业任务异常，批次号：" + batchTask.getBatchTaskCode());
		}

	}
	
	/**
	 * 设置库位、箱位——多件
	 * @param workOrderList  作业订单集合
	 * @param customerCode 商户编码
	 * @param warehouseCode 仓库编码
	 * @return
	 */
	private String setBoxCode_multi(List<BackupTaskOrdeno> workOrderList, String customerCode,String warehouseCode) {
        
		String errorList="";
		
		// sku数量分类
		Map<String, Integer> skuMap = new HashMap<String, Integer>();
		for (BackupTaskOrdeno o : workOrderList) {
			List<EdiOrderItem> eOrderList=o.getOrderItems();
			for (EdiOrderItem ediOrderItem : eOrderList) {
				String sku = ediOrderItem.getSku();
				Integer num=ediOrderItem.getQty();
				if (skuMap.containsKey(sku)) {
					skuMap.put(sku,skuMap.get(sku) + num);
				} else {
					skuMap.put(sku, num);
				}
			}
		}

		// 给每个sku分配库存
		for (String sku : skuMap.keySet()) {
			int sku_num = skuMap.get(sku); // 每个sku需求数量.
//			List<CusStock> stockList = this.cusStockDao.loadStock(warehouseCode, customerCode, sku);
			List<CusStock> stockList = this.cusStockDao.loadStock(customerCode, sku);
			
			// 排序：商品数量升序排列，
			Collections.sort(stockList, new Comparator<CusStock>() {
				public int compare(CusStock o1, CusStock o2) {
					return o1.getSalesNum().compareTo(o2.getSalesNum());
				}
			});

			boolean flag = false;
			// 找到最接近满足的箱位
			for (CusStock cusStock : stockList) {
				if (cusStock.getSalesNum() >= sku_num) { 

					for (BackupTaskOrdeno pOrder : workOrderList) {
						
						String _stockInfo = pOrder.getStockInfo();
						
						Map<String, Integer> stockInfoMap=this.stockInfo2Map(_stockInfo);
						
						List<EdiOrderItem> eOrderList=pOrder.getOrderItems();
						for (EdiOrderItem ediOrderItem : eOrderList) {
							
							String _sku = ediOrderItem.getSku();
							Integer _num=ediOrderItem.getQty();
							
							if( _sku.equals(sku) && !stockInfoMap.containsKey(_sku)){
								String info=cusStock.getStockCode() + "_" + cusStock.getBoxCode() + "_" + _sku + "_" + _num + ";";
								if(_stockInfo==null){
									pOrder.setStockInfo(info);
								}else{
									pOrder.setStockInfo(pOrder.getStockInfo()+info);
								}
							}
							
						}
						
					}
					
					sku_num = 0;
					cusStock.setSalesNum(cusStock.getSalesNum()-sku_num);
					flag = true;
					break;
				}
			}
			
			// 如果没有找到最接近的箱位，箱位组合分配。
			if (!flag) {
				Collections.reverse(stockList); // 排序，商品数量降序
				for (CusStock cusStock : stockList) {
					int salesNum=cusStock.getSalesNum();
					while(true){
						Boolean flag1=true;
						this.setBoxCode(cusStock,workOrderList,flag1);
						salesNum=cusStock.getSalesNum();
						if(salesNum<=0 || flag1==true){
							break;
						}
						
					}
				}
			}
			
			if(sku_num>0){
				if(errorList.length()>0){
					errorList+=",";
				}
				errorList+=sku;
			}

		}
		return errorList;
	}
	
	/**
	 * 库位信息转化: String->map形式
	 * @param stockInfo
	 * @return
	 */
	private Map<String, Integer>  stockInfo2Map(String stockInfo) {
		Map<String, Integer> map=new HashMap<String, Integer>();
		if(StringUtils.isBlank(stockInfo)){
			return map;
		}
		String[] stockInfoArray=stockInfo.split(";");
		for (String  info : stockInfoArray) {
			if(StringUtils.isNotBlank(info)){
				String[] _info=info.split("_");
				String sku=_info[2];
				Integer num=Integer.valueOf(_info[3]);
				if(map.keySet().contains(sku)){
					map.put(sku,map.get(sku)+num);
				}else{
					map.put(sku, num);	
				}
			}
		}
		
        return map;		
	}
	
	
public void setBoxCode(CusStock cusStock,List<BackupTaskOrdeno> workOrderList,Boolean flag){
		
		String cusStockSku=cusStock.getSku();
		
		for(BackupTaskOrdeno workOrder:workOrderList){
			
			String stockInfo = workOrder.getStockInfo()==null?"":workOrder.getStockInfo();
			Map<String, Integer> stockInfoMap=this.stockInfo2Map(stockInfo);
			
			List<EdiOrderItem> eOrderList=workOrder.getOrderItems();
			
			for (EdiOrderItem ediOrderItem : eOrderList) {
				String sku=ediOrderItem.getSku();
				
				if(sku.equals(cusStockSku)){

					int needNum=ediOrderItem.getQty();
					int stockNum=cusStock.getSalesNum();
					String _stockInfo="";
					
					if(stockNum<=0){
						break;
					}
					
					if(stockInfoMap.containsKey(sku)){
						int existsNum=stockInfoMap.get(sku);
						int lessNum=needNum-existsNum;
						if(lessNum>0){
							if(stockNum>lessNum){
								cusStock.setSalesNum(cusStock.getSalesNum()-lessNum);
								_stockInfo=cusStock.getStockCode()+"_"+cusStock.getBoxCode()+"_"+cusStock.getSku()+"_"+lessNum+";";
							}else{
								cusStock.setSalesNum(0);
								_stockInfo=cusStock.getStockCode()+"_"+cusStock.getBoxCode()+"_"+cusStock.getSku()+"_"+stockNum+";";
								flag=false;
							}
						}
						
					}else{
						if(stockNum>=needNum){
							cusStock.setSalesNum(cusStock.getSalesNum()-needNum);
							_stockInfo=cusStock.getStockCode()+"_"+cusStock.getBoxCode()+"_"+cusStock.getSku()+"_"+needNum+";";
						}else{
							cusStock.setSalesNum(0);
							_stockInfo=cusStock.getStockCode()+"_"+cusStock.getBoxCode()+"_"+cusStock.getSku()+"_"+stockNum+";";
							flag=false;
						}
					}
					workOrder.setStockInfo(stockInfo+_stockInfo);
				}
				
			}
			
		}
		
	}
	
}
